//
//  MainViewModel.swift
//  Automobile
//
//  Created by erkebulan elzhan on 8/12/20.
//  Copyright © 2020 erkebulan elzhan. All rights reserved.
//

import UIKit

typealias CarHeaderCellConfigurator = TableCellConfigurator<CarHeaderCell, MainViewModel.CarHeader?>
typealias CarInfoCellConfigurator = TableCellConfigurator<CarInfoCell, MainViewModel.CarInfoItems?>
typealias CarDescriptionCellConfigurator = TableCellConfigurator<CarDescriptionCell, String?>
typealias CarContactsCellConfigurator = TableCellConfigurator<CarContactsCell, MainViewModel.CarContacts?>
typealias CarSimilarAdsCellConfigurator = TableCellConfigurator<SimilarAdsCell, [PostModel]?>
typealias CarFooterCellConfigurator = TableCellConfigurator<CarFooterCell, MainViewModel.CarFooterContacts?>
typealias CarHelperCellConfigurator = TableCellConfigurator<CarHelperCell, Any?>

typealias CarWarnCellConfigurator = TableCellConfigurator<CarWarnCell, String?>
typealias CarHistoryCellConfigurator = TableCellConfigurator<CarHistoryCell, [MainViewModel.CarHistoryItems]?>
typealias CarPriceCellConfigurator = TableCellConfigurator<CarPriceCell, MainViewModel.CarPriceItem?>

protocol MainViewModelDelegate {
    func loadPost (post: Post)
    func updatePost ()
}

final class MainViewModel {

    var viewModelDelegate: MainViewModelDelegate!
    var delegate: ViewModelProtocol!
    
    var post: Post!
    var postID: Int?
    
    var items: [CellConfigurator] = []
    
    let menuItems = [
        MenuPopup.MenuItem(icon: UIImage(named: "help"), title: "Сообщение"),
        MenuPopup.MenuItem(icon: UIImage(named: "podderzhka"), title: "Пожаловаться")
    ]
    
    var isPreview = false
    
    
    private let backendService = Backend()
    
    public func update () {
        let postModel = PostModel(post: post)
        
        var _items = [
            CarHeaderCellConfigurator(item: CarHeader(postModel: postModel)),
            
            CarInfoCellConfigurator(item: CarInfoItems(car: post.car, city: post.city, ruleType: post.ruleType))

        ] as [CellConfigurator]
        
        if let description = post.description {
            _items.append(CarDescriptionCellConfigurator(item: description))
        }
        
        if isPreview {
            _items.append(CarContactsCellConfigurator(item:
                CarContacts(city: post.city,
                            name: post.contactName,
                            email: post.contactEmail)))
        } else {
            
            _items.append(CarWarnCellConfigurator(item: nil))
            
            if post.car.carNumber != nil && post.car.carNumber?.vin != nil && post.car.carNumber?.vin != "" {
                
                _items.append(CarHistoryCellConfigurator(item: [
                    CarHistoryItems(name: "ДТП", data: post.car.dtp_status),
                    CarHistoryItems(name: "истории перерегистрации", data: post.car.history_status)
                ]))
                
                let carPriceitem = CarPriceItem(fullCarName: [postModel.marka, postModel.model,
                                                              postModel.pokolenie,
                                                              postModel.serie,
                                                              postModel.pokolenie].joined(separator: " "),
                                                carNumber: postModel.post.car.carNumber,
                                                carPrice: postModel.post.price)
                _items.append(CarPriceCellConfigurator(item: carPriceitem))
            }
            
            _items.append(CarHelperCellConfigurator(item: nil))
            
            // TODO: UPDATE IT
            _items.append(CarSimilarAdsCellConfigurator(item: [postModel, postModel, postModel]))
            
            _items.append(CarFooterCellConfigurator(item: nil))
        }
        
        self.items = _items
    }
}

extension MainViewModel {
    
    public func updatePost (city: City?, name: String?, email: String?) {
        let advertID = post.id
        
        var request = URLRequest(url: Request(base: .advert).getUrl(path: "adverts/my/\(advertID)/"))
        request.httpMethod = "PATCH"
        
        let data = ["contact_email": email as Any, "contac as Anyt_name": name, "city": city?.id as Any] as [String : Any]

        delegate.updateSpinner(showSpinner: true)
        
        backendService.fetchFromBackend(for: Bool.self, request: request, statusCode: 200, sendBool: true, sendBody: true, body: data) { (result) in
            self.delegate.updateSpinner(showSpinner: false)
            switch result {
            case .failure(let err):
                self.delegate.didHappenError(error: err)
            case .success(_):
                self.viewModelDelegate.updatePost()
            }
        }
    }
    
    public func loadPost () {
        let advertID = self.post.id
        let requestURL = Request(base: .advert).getUrl(path: "adverts/all/\(advertID)/")
        let request = URLRequest(url: requestURL)
        
        delegate.updateSpinner(showSpinner: true)
        
        backendService.fetchFromBackend(for: Post.self, request: request, statusCode: 200) { (result) in
            self.delegate.updateSpinner(showSpinner: false)
            switch result {
            case .failure(let err):
                self.delegate.didHappenError(error: err)
            case .success(let post):
                self.post = post
                self.update()
                self.viewModelDelegate.loadPost(post: post)
            }
        }
    }
    
    public func addToFavorite () {
        let advertID = post.id
        let isRemove = post.isLiked
        
        self.delegate.updateSpinner(showSpinner: true)
        backendService.addToFavorites(advertID: advertID, isRemove: isRemove) { (isSuccess, err) in
            self.delegate.updateSpinner(showSpinner: false)
            if isSuccess {
                self.post.isLiked.toggle()
                self.delegate.updatePosts()
            } else {
                self.delegate.didHappenError(error: .parameter(err!))
            }
        }
    }
}


extension MainViewModel {
    
    struct CarHeader {
        var images: [PostImage]?
        var price: String
        var visCount: String
        var titleString: String
        var localImgs: [UIImage] = []
        var postMarketing: PostReklama?
        var date: String
        
        init (postModel: PostModel) {
            self.images = postModel.images
            self.price = postModel.price
            self.visCount = postModel.visCount
            self.titleString = [postModel.marka, postModel.model, postModel.pokolenie, postModel.serie, postModel.pokolenie].joined(separator: " ")
            self.localImgs = postModel.localImages
            self.postMarketing = postModel.postMarketing
            self.date = postModel.date
        }
    }
    
    struct CarInfoItems {
        
        var car: Car!
        var city: City?
        var ruleType: RuleType?
        
        
        init (car: Car, city: City?, ruleType: RuleType? = nil) {
            self.car = car
            self.city = city
            self.ruleType = ruleType
        }
        
        public lazy var items: [ItemsStack.KeyValueItem] = [
            ItemsStack.KeyValueItem(value: self.regionText, hint: "Регион"),
            ItemsStack.KeyValueItem(value: self.yearText, hint: "Год выпуска"),
            ItemsStack.KeyValueItem(value: self.kuzovText, hint: "Кузов"),
            ItemsStack.KeyValueItem(value: self.colorText, hint: "Цвет"),
            ItemsStack.KeyValueItem(value: self.dvigatelText, hint: "Двигатель"),
            ItemsStack.KeyValueItem(value: self.korobkaText, hint: "КПП"),
            ItemsStack.KeyValueItem(value: self.privodText, hint: "Привод"),
            ItemsStack.KeyValueItem(value: self.ruleText, hint: "Руль"),
            ItemsStack.KeyValueItem(value: self.vinText, hint: "VIN"),
            ItemsStack.KeyValueItem(value: self.gosNumber, hint: "Госномер"),
            ItemsStack.KeyValueItem(value: self.rastomozhenText, hint: "Растоможен")
        ]
        
        private var regionText: String {
            return city?.region.name ?? "Неизвестно"
        }
        
        private var yearText: String {
            return car.year != nil ? "\(car.year!)" : "Неизвестно"
        }
        
        private var kuzovText: String {
            return car.serie?.name ?? "Неизвестно"
        }
        
        private var colorText: String {
            return car.color?.name ?? "Неизвестно"
        }
        
        private var dvigatelText: String {
            return car.engineType?.name ?? "Неизвестно"
        }
        
        private var korobkaText: String {
            return car.transmissionType?.name ?? "Неизвестно"
        }
        
        private var privodText: String {
            return car.driveType?.name ?? "Неизвестно"
        }
        
        private var ruleText: String {
            return ruleType?.display ?? "Неизвестно"
        }
        
        private var vinText: String {
            if let carNumber = car.carNumber {
                if let vin = carNumber.vin {
                    if vin.count > 3 {
                        return vin[..<vin.index(vin.startIndex, offsetBy: 3)] + "**********"
                    } else {
                        return vin
                    }
                } else {
                    return "Неизвестно"
                }
            } else {
                return "Неизвестно"
            }
        }
        
        private var gosNumber: String {
            if let carNumber = car.carNumber {
                if carNumber.isNewFormat {
                    return "KZ ******|**"
                } else {
                    return "KZ *|******"
                }
            } else {
                return "Неизвестно"
            }
        }
        
        private var rastomozhenText: String {
            return "Да"
        }
    }
    
    struct CarContacts {
        var city: City?
        var name: String?
        var email: String?
    }
    
    struct CarFooterContacts {
        var phoneNumber: String
    }
    
    struct CarHistoryItems {
        var name: String
        var data: HistoryStatus
    }
    
    struct CarPriceItem {
        var fullCarName: String
        var carNumber: CarNumber?
        var carPrice: Int?
    }
}
